// Author: Domien Nowicki

#include "CellWidget.h"
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
#include <QStyleOption>
#include <malloc.h>

CellWidget::CellWidget(QGraphicsScene *scene, unsigned int mapX, unsigned int mapY): Cell(mapX, mapY), highlight(false)
{
	SetupWidget(scene);
}



CellWidget::CellWidget(QGraphicsScene *scene, const Cell& rhs): Cell(rhs), highlight(false)
{
	SetupWidget(scene);
}

void CellWidget::SetupWidget(QGraphicsScene *scene)
{
	bounds = QRectF(0, 0, ITEMSIZE, ITEMSIZE);	
	path.addRect(0, 0, ITEMSIZE, ITEMSIZE);

	// Clear all cellside widgets
	for(unsigned int i=0; i<Cell::SIDECOUNT; i++)
		sides[i] = 0;

	SetMapPos(GetMapX(), GetMapY());

	if (scene)
		scene->addItem(this);

	setAcceptsHoverEvents(true);
	setZValue(ITEMZ);

	// Setup wall or empty cell
	if (IsEmpty())
	{
		SetEmpty();
	}
	else
	{
		SetWall();
	}
}

CellWidget::~CellWidget()
{
	Clear();
}

void CellWidget::Clear()
{
	// Remove all side widgets
	for(unsigned int i=0; i<Cell::SIDECOUNT; i++)
	{
		RemoveSide(i);
	}
}


QRectF CellWidget::boundingRect() const
{
	return bounds;
}

QPainterPath CellWidget::shape() const
{
	return path;
}

void CellWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	painter->setPen(QColor(255,255,255));

	QColor color = Qt::darkBlue;

	// darkblue = empty
	// purple = wall

	if (!IsEmpty())
	{
		color.setRed(200);
	}

	// Draw cell square
	painter->setBrush(color);
	painter->drawRect(bounds);

	// Hightlight cell
	if (highlight)
	{
		color.setAlpha(100);
		color.setRed( 255 - color.red());
		color.setGreen( 255 - color.green());
		color.setBlue( 255 - color.blue());

		painter->setBrush(color);
		painter->drawRect(bounds);
	}

}

void CellWidget::hoverEnterEvent(QGraphicsSceneHoverEvent *e)
{
	highlight = true;
	update();
}

void CellWidget::hoverLeaveEvent(QGraphicsSceneHoverEvent *e)
{
	highlight = false;
	update();
}

void CellWidget::mousePressEvent(QGraphicsSceneMouseEvent *e)
{
	emit clicked(this);
}

void CellWidget::SetMapPos(unsigned int mapX, unsigned int mapY)
{	
	setPos(mapX*ITEMSIZE, mapY*ITEMSIZE);

	Cell::SetMapPos(mapX, mapY);
}

void CellWidget::SetWall()
{
	Cell::SetWall();

	// Remove all sides
	for(unsigned int i=0; i<Cell::SIDECOUNT; i++)
	{
		RemoveSide(i);
	}

	// Add front, back, left and right for a wall
	for(unsigned int i=0; i<Cell::SIDECOUNT; i++)
	{
		switch(i)
		{
			case Cell::FRONT:
			case Cell::BACK:
			case Cell::LEFT:
			case Cell::RIGHT:
				AddSide(i);
			break;

			default:
				continue;
		}
	}

	update();
}

void CellWidget::SetEmpty()
{
	Cell::SetEmpty();


	// Remove all sides
	for(unsigned int i=0; i<Cell::SIDECOUNT; i++)
	{
		RemoveSide(i);
	}

	// Add ceiling and floor
	AddSide(Cell::CEILING);
	AddSide(Cell::FLOOR);

	update();
}



void CellWidget::slotClickedSide(CellSideWidget* side)
{
	// Emit which side was clicked, and for which cell
	emit clickedSide(this, side->GetSide());
}

// Set texture and usercolor for a side
void CellWidget::SetTexture(Cell::Side side, unsigned int tindex, const Pixel& userColor)
{
	unsigned int sindex = (unsigned int)side;
	Cell::SetTexture(side, tindex, userColor);

	if (sides[sindex])
	{
		sides[sindex]->SetSideColor(userColor);
	}

	update();
}

// Remove a side 
void CellWidget::RemoveSide(unsigned int sindex)
{
	if (0 != sides[sindex])
	{
		QGraphicsScene *currentScene = scene();

		if (currentScene)
		{
			currentScene->removeItem( sides[sindex] );
		}

		delete sides[sindex];
		sides[sindex] = 0;
	}
}

// Add a side
void CellWidget::AddSide(unsigned int sindex)
{
	if (0 == sides[sindex])
	{
		Cell::Side side = (Cell::Side)sindex;
		sides[sindex] = new CellSideWidget(side, this);

		QObject::connect( sides[sindex], SIGNAL( clicked(CellSideWidget*) ), this, SLOT( slotClickedSide(CellSideWidget*) ) );
		sides[sindex]->setPos( pos() );

		QGraphicsScene *currentScene = scene();
		if (currentScene)
		{
			currentScene->addItem(sides[sindex]);
		}

		sides[sindex]->SetSideColor( GetUserColor(side) );
	}
}

// Update all sides with their usercolors
void CellWidget::UpdateSides()
{
	for(unsigned int i=0; i<Cell::SIDECOUNT; i++)
	{
		Cell::Side side = (Cell::Side)i;

		if (sides[i])
		{
			sides[i]->SetSideColor( GetUserColor(side) );
		}
	}
}
